import { TrendListDto } from '@/dtos';
import { ok } from '@/utils';
import { Body, Controller, Post } from '@nestjs/common';
import { BaseController } from './base.controller';
import { TokenStatusEnum } from '@/enums';
import { random } from 'radash';

@Controller('trend')
export class TrendController extends BaseController {
  @Post('list')
  async list(@Body() { params, sort }: TrendListDto) {
    const { current = 1, pageSize = 20, keyword, ...where } = params;

    let sql = `
            SELECT #{fields} FROM Asset AS t
            LEFT JOIN Album AS a ON a.id = t.albumId
            WHERE t.isDeleted = false
              AND t.isTradable = true
        `;

    const [{ count }] = await this.prisma.$queryRawUnsafe<[{ count: number }]>(
      sql.replace('#{fields}', 'COUNT(t.id) AS count'),
    );

    const list = await this.prisma.$queryRawUnsafe<any[]>(
      `${sql.replace(
        '#{fields}',
        `
            t.id, t.title, t.limit, t.image, t.circulation,
             (
                SELECT (COUNT(o.id) * 120) + (COUNT(o.id) * FLOOR(RAND() * 12) + 1)
                FROM \`Order\` AS o
                WHERE o.assetId = t.id
                    AND o.createdAt > DATE_SUB(NOW(), INTERVAL 24 HOUR)
            ) AS hot,
            (
                SELECT COUNT(tt.id)
                FROM Token AS tt
                WHERE tt.assetId = t.id
                AND (
                    tt.status = ${TokenStatusEnum.ON_SALE}
                    OR
                    tt.status = ${TokenStatusEnum.LOCKING}
                ) 
            ) AS num, 
            (
                SELECT MIN(tt.price)
                FROM Token AS tt
                WHERE tt.assetId = t.id
                AND (
                    tt.status = ${TokenStatusEnum.ON_SALE}
                    OR
                    tt.status = ${TokenStatusEnum.LOCKING}
                ) 
            ) AS price
        `,
      )}
        ORDER BY ${
          !!sort && Object.keys(sort).length > 0
            ? Object.entries(sort)
                .map(([k, v]) => {
                  if (['hot', 'price'].includes(k)) {
                    return `${k} ${v === 'descend' ? 'DESC' : 'ASC'}`;
                  }
                  return `t.${k} ${v === 'descend' ? 'DESC' : 'ASC'}`;
                })
                .join(',')
            : 't.createdAt DESC'
        }
        LIMIT ${pageSize} 
        OFFSET ${(current - 1) * pageSize}
    `,
    );

    const total = count ? Number(count) : 0;
    const totalPage = Math.ceil(total / pageSize);
    const hasMore = current < totalPage;

    return ok({
      total,
      totalPage,
      hasMore,
      current,
      pageSize,
      list: list.map((o) => ({
        ...o,
        price: Number(o.price),
        hot: Number(o.hot),
        num: Number(o.num),
      })),
    });
  }
}
